home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
VECTBAL2.ZIP
/
VECTBAL2.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-04
|
11KB
|
467 lines
//////////////////////////////////
// VECTOR BALLS 2 //
// (c) 1994 by Bodies In Motion //
// code - Tumblin //
// graphics - Rush //
//////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <dos.h>
#include <xlib_all.h>
// include the palette and bitmap data of the vector ball
#include "vectbal2.h"
//──────────────────────── fixed point math code ─────────────────────────
typedef long Fixedpoint;
#define Int2Fixed(a) (Fixedpoint)((Fixedpoint)(a) << 16)
#define Fixed2Int(a) (int)((a) >> 16)
#define Float2Fixed(a) ((Fixedpoint)((a) * 65536.0))
#define Fixed2Float(a) ((a) / 65536.0)
extern "C" {
Fixedpoint FixedMul(Fixedpoint,Fixedpoint);
Fixedpoint FixedDiv(Fixedpoint,Fixedpoint);
};
//──────────────────────── some helpful constants ────────────────────────
// maximum # of degrees for sin and cos tables
#define MAXDEGREES 720
// distance from users eye to screen surface in pixels
#define EYE_DISTANCE Int2Fixed(256)
// depth to push objects into the screen
#define DEPTH Int2Fixed(1024)
// maximum number of balls an object can have
#define MAXBALLS 100
//──────────────────────────── data structures ───────────────────────────
//────────────────────────────────────────────────────────────────────────
char filename[80];
Fixedpoint cosine[MAXDEGREES]; // cosine lookup table
Fixedpoint sine[MAXDEGREES]; // sine lookup table
typedef struct
{
Fixedpoint ox,oy,oz; // origional x,y,z coordinates of ball
Fixedpoint wx,wy,wz; // working copy of x,y,z coordinates of ball
int sx,sy,sz; // screen coordinates of ball
} BallTYPE;
int NumOfBalls=0; // current number of defined balls in object
BallTYPE Ball[MAXBALLS]; // object containing MAXBALLS balls
int SBall[MAXBALLS]; // indexes to ball structures (for qsorting)
int XAngle=0; // degrees to rotate object around x axis
int YAngle=0; // degrees to rotate object around y axis
int ZAngle=0; // degrees to rotate object around z axis
// bounding erase box
int EraseLeft; // current frame
int EraseTop; // current frame
int EraseRight; // current frame
int EraseBottom; // current frame
int EraseLeft1; // from 1 frame ago
int EraseTop1; // from 1 frame ago
int EraseRight1; // from 1 frame ago
int EraseBottom1; // from 1 frame ago
int EraseLeft2; // from 2 frames ago
int EraseTop2; // from 2 frames ago
int EraseRight2; // from 2 frames ago
int EraseBottom2; // from 2 frames ago
unsigned char old_palette[768];
unsigned char current_palette[768]={0};
//───────────────────────────── function prototypes ────────────────────────
void main(int argc,char *argv[]);
void InitSinCosTables(void);
void InitSortList(void);
int LoadObject(char * filename);
void UpdateBalls(void);
int CompareBalls(const void *a, const void *b);
void WaitVerticalRetrace(void);
void FadeInPalette(unsigned char *,int);
void FadeOutPalette(int);
void GetPalette(unsigned char *);
void SetPalette(unsigned char *);
void FadeInOne64th(unsigned char *,unsigned char *);
void FadeOutOne64th(unsigned char *);
//──────────────── code to create sin and cos lookup tables ──────────────
void InitSinCosTables(void)
{
int i;
for(i=0; i<MAXDEGREES; i++)
{
cosine[i]=Float2Fixed(cos((float)i*360/MAXDEGREES * 3.14159265 / 180.0));
sine[i] =Float2Fixed(sin((float)i*360/MAXDEGREES * 3.14159265 / 180.0));
}
}
//──────────────────── initialize the sorted ball list ──────────────────────
void InitSortList(void)
{
// point each element to an initial ball
for(int i=0; i<MAXBALLS; i++)
{
SBall[i]=i;
}
}
//────────────────────────── compare balls (for qsort) ─────────────────────
int CompareBalls(const void *a, const void *b)
{
if( Ball[*(int *)a].sz < Ball[*(int *)b].sz )
{
return -1;
}
else if( Ball[*(int *)a].sz > Ball[*(int *)b].sz )
{
return +1;
}
else
{
return 0;
}
}
//──────────────────────── update vector ball object ─────────────────────
void UpdateBalls(void)
{
int i;
Fixedpoint nx,ny,nz;
Fixedpoint sinxangle,cosxangle;
Fixedpoint sinyangle,cosyangle;
Fixedpoint sinzangle,coszangle;
// initialize the bounding box to its extremes
EraseLeft=320;
EraseTop=240;
EraseRight=0;
EraseBottom=0;
// get the sine and cosine angles to save time from table lookup
sinxangle=sine[XAngle];
cosxangle=cosine[XAngle];
sinyangle=sine[YAngle];
cosyangle=cosine[YAngle];
sinzangle=sine[ZAngle];
coszangle=cosine[ZAngle];
// rotate the balls
for(i=0;i<NumOfBalls;i++)
{
// rotate around the x-axis
Ball[i].wz=FixedMul(Ball[i].oy,cosxangle) - FixedMul(Ball[i].oz,sinxangle);
Ball[i].wy=FixedMul(Ball[i].oy,sinxangle) + FixedMul(Ball[i].oz,cosxangle);
Ball[i].wx=Ball[i].ox;
// rotate around the y-axis
nx=FixedMul(Ball[i].wx,cosyangle) - FixedMul(Ball[i].wz,sinyangle);
nz=FixedMul(Ball[i].wx,sinyangle) + FixedMul(Ball[i].wz,cosyangle);
Ball[i].wx=nx;
Ball[i].wz=nz;
// rotate around the z-axis
nx=FixedMul(Ball[i].wx,coszangle) - FixedMul(Ball[i].wy,sinzangle);
ny=FixedMul(Ball[i].wx,sinzangle) + FixedMul(Ball[i].wy,coszangle);
Ball[i].wx=nx;
Ball[i].wy=ny;
// project the 3-D coordinates to screen coordinates
Ball[i].sx=Fixed2Int(FixedMul(FixedDiv(Ball[i].wx,Ball[i].wz - DEPTH),EYE_DISTANCE)) + 160;
Ball[i].sy=Fixed2Int(FixedMul(FixedDiv(Ball[i].wy,Ball[i].wz - DEPTH),EYE_DISTANCE)) + 120;
Ball[i].sz=Fixed2Int(Ball[i].wz-DEPTH);
// and while we're at it, find the bounding box for erasing balls
if(Ball[i].sx < EraseLeft)
{
EraseLeft=Ball[i].sx;
}
if(Ball[i].sy < EraseTop)
{
EraseTop=Ball[i].sy;
}
if(Ball[i].sx > EraseRight)
{
EraseRight=Ball[i].sx;
}
if(Ball[i].sy > EraseBottom)
{
EraseBottom=Ball[i].sy;
}
}
// sort the balls according to their z coordinate
qsort((const void *)SBall,NumOfBalls,sizeof(SBall[0]),CompareBalls);
// erase the balls from 2 frames ago (remember, we're double buffering)
x_rect_fill(EraseLeft2-12,EraseTop2-12,
EraseRight2+16,EraseBottom2+16,
HiddenPageOffs,0);
// draw the new balls onto the screen
for(i=0; i<NumOfBalls; i++)
{
x_put_masked_pbm(Ball[SBall[i]].sx-12,Ball[SBall[i]].sy-12,
HiddenPageOffs,bitmap);
}
// update the bounding boxes for this frame
EraseTop2=EraseTop1;
EraseLeft2=EraseLeft1;
EraseRight2=EraseRight1;
EraseBottom2=EraseBottom1;
EraseTop1=EraseTop;
EraseLeft1=EraseLeft;
EraseRight1=EraseRight;
EraseBottom1=EraseBottom;
}
//────────── load a dot object for use as a vector ball object ───────────
int LoadObject(char *filename)
{
int i,temp;
FILE *file;
// open the file to read from it
if ((file = fopen(filename,"rb")) == NULL)
{
printf("\n\nCannot open input file.\n");
return (0);
}
else
{
// okay file is ready to read data from it
// read number of dots in file
fread(&NumOfBalls,sizeof(int),1,file);
// read in all of the object's dots
for(i=0;i < NumOfBalls; i++)
{
fread(&temp,sizeof(int),1,file);
Ball[i].ox=Int2Fixed(temp);
fread(&temp,sizeof(int),1,file);
Ball[i].oy=Int2Fixed(temp);
fread(&temp,sizeof(int),1,file);
Ball[i].oz=Int2Fixed(temp);
}
// we're finished, close the file
fclose(file);
return (1);
}
}
//──────────────────────── palette fading code ───────────────────────────
void WaitVerticalRetrace(void)
{
asm mov dx,3dah
top_of_retrace:
asm in al,dx
asm and al,08h
asm jnz top_of_retrace
bottom_of_retrace:
asm in al,dx
asm and al,08h
asm jz bottom_of_retrace
}
void GetPalette(unsigned char *palettebuffer)
{
int i;
for(i=0;i<256;i++)
{
outp(0x3c7,i); // color number to get data from
palettebuffer[i*3] = inp(0x3c9); // red
palettebuffer[i*3+1] = inp(0x3c9); // green
palettebuffer[i*3+2] = inp(0x3c9); // blue
}
}
void SetPalette(unsigned char *palettebuffer)
{
int i;
for(i=0;i<256;i++)
{
outp(0x3c8,i); // color number to set
outp(0x3c9,palettebuffer[i*3]); // red
outp(0x3c9,palettebuffer[i*3+1]); // green
outp(0x3c9,palettebuffer[i*3+2]); // blue
}
}
void FadeInPalette(unsigned char *palettebuffer,int speed)
{
int i,j,k;
unsigned char temppalette[768]={0};
for(i=0;i<64;i++)
{
for(j=0;j<256;j++)
{
// do the red component
if(temppalette[j*3] < palettebuffer[j*3])
{
temppalette[j*3]++;
}
// do the green component
if(temppalette[j*3+1] < palettebuffer[j*3+1])
{
temppalette[j*3+1]++;
}
// do the blue component
if(temppalette[j*3+2] < palettebuffer[j*3+2])
{
temppalette[j*3+2]++;
}
}
for(k=0;k<speed;k++)
{
WaitVerticalRetrace();
}
SetPalette(temppalette);
}
}
void FadeOutPalette(int speed)
{
int i,j,k;
unsigned char temppalette[768];
GetPalette(temppalette);
for(i=0;i<64;i++)
{
for(j=0;j<256;j++)
{
// do the red component
if(temppalette[j*3] > 0)
{
temppalette[j*3]--;
}
// do the green component
if(temppalette[j*3+1] > 0)
{
temppalette[j*3+1]--;
}
// do the blue component
if(temppalette[j*3+2] > 0)
{
temppalette[j*3+2]--;
}
}
for(k=0;k<speed;k++)
{
WaitVerticalRetrace();
}
SetPalette(temppalette);
}
}
//───────────────────────────── main program ─────────────────────────────
void main(int argc,char *argv[])
{
if(argc<=1)
{
printf("┌─────────────────┐\n");
printf("│ VECTOR BALLS II │\n");
printf("└─────────────────┘\n");
printf("Syntax: VECTBAL2 filename.DOT\n\n");
exit(1);
}
if(LoadObject(argv[1])==0)
{
printf("Error: could not find that file.\n");
exit(1);
}
InitSinCosTables();
InitSortList();
GetPalette(old_palette);
SetPalette(current_palette);
_setcursortype(_NOCURSOR);
clrscr();
printf("\n\n\n\n\n\n\n\n");
printf(" ┌──────────────────────────────┐\n");
printf(" │ VECTOR BALLS II │\n");
printf(" │ (c) 1994 by Bodies In Motion │\n");
printf(" │ code - Tumblin │\n");
printf(" │ graphics - Rush │\n");
printf(" └──────────────────────────────┘\n\n\n");
FadeInPalette(old_palette,2);
delay(1000);
FadeOutPalette(2);
x_set_mode(X_MODE_320x240,320);
x_set_doublebuffer(240);
x_put_pal_raw(palette,256,0);
delay(1000);
do
{
XAngle+=6;
if(XAngle >= MAXDEGREES)
{
XAngle -= MAXDEGREES;
}
YAngle+=4;
if(YAngle >= MAXDEGREES)
{
YAngle -= MAXDEGREES;
}
ZAngle+=3;
if(ZAngle >= MAXDEGREES)
{
ZAngle -= MAXDEGREES;
}
UpdateBalls();
x_page_flip(0,0);
} while(!kbhit());
getch();
x_text_mode();
for(int i=0;i<256;i++)
{
current_palette[i]=0;
}
SetPalette(current_palette);
printf("We hope this has been a 'moving' experience.");
delay(1000);
FadeInPalette(old_palette,1);
_setcursortype(_NORMALCURSOR);
}